
#include "usb_conf.h"
#include "diskio.h"
#include "usbh_msc_core.h"
/*--------------------------------------------------------------------------

Module Private Functions and Variables

---------------------------------------------------------------------------*/

volatile DSTATUS Stat = STA_NOINIT;	/* Disk status */

extern USB_OTG_CORE_HANDLE          USB_OTG_Core;
extern USBH_HOST                     USB_Host;

/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive                                                 */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE drv		/* Physical drive number (0) */
	)
{
	if (HCD_IsDeviceConnected(&USB_OTG_Core))
		Stat &= ~STA_NOINIT;
	return Stat;
}



/*-----------------------------------------------------------------------*/
/* Get Disk Status                                                       */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE drv		/* Physical drive number (0) */
	)
{
	if (drv)
		return STA_NOINIT;		/* Supports only single drive */
	return Stat;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE drv,			/* Physical drive number (0) */
	BYTE *buff,			/* Pointer to the data buffer to store read data */
	DWORD sector,		/* Start sector number (LBA) */
	UINT count			/* Sector count (1..255) */
	)
{
	BYTE status = USBH_MSC_OK;
  
	if (drv || !count) return RES_PARERR;
	if (Stat & STA_NOINIT) return RES_NOTRDY;

	if (HCD_IsDeviceConnected(&USB_OTG_Core))
	{

		do
		{
			status = USBH_MSC_Read10(&USB_OTG_Core, buff, sector, 512 * count);
			USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);

			if (!HCD_IsDeviceConnected(&USB_OTG_Core))
				return RES_ERROR;

		} while (status == USBH_MSC_BUSY );
	}

	if (status == USBH_MSC_OK)
		return RES_OK;
	return RES_ERROR;
  
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if _READONLY == 0
DRESULT disk_write (
	BYTE drv,			/* Physical drive number (0) */
	const BYTE *buff,	/* Pointer to the data to be written */
	DWORD sector,		/* Start sector number (LBA) */
	UINT count			/* Sector count (1..255) */
	)
{
	BYTE status = USBH_MSC_OK;

	if (drv || !count) return RES_PARERR;
	if (Stat & STA_NOINIT) return RES_NOTRDY;
	if (Stat & STA_PROTECT) return RES_WRPRT;

	if (HCD_IsDeviceConnected(&USB_OTG_Core))
	{  
		do
		{
			status = USBH_MSC_Write10(&USB_OTG_Core,(BYTE*)buff,sector,512 * count);
			USBH_MSC_HandleBOTXfer(&USB_OTG_Core, &USB_Host);

			if (!HCD_IsDeviceConnected(&USB_OTG_Core))
				return RES_ERROR;
		} while (status == USBH_MSC_BUSY );
	}

	if (status == USBH_MSC_OK)
		return RES_OK;
	return RES_ERROR;
}
#endif /* _READONLY == 0 */



/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

#if _USE_IOCTL != 0
DRESULT disk_ioctl (
	BYTE drv,		/* Physical drive number (0) */
	BYTE ctrl,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
	)
{
  DRESULT res = RES_OK;
  
	if (drv) return RES_PARERR;

	res = RES_ERROR;
	if (Stat & STA_NOINIT)
		return RES_NOTRDY;
  
	switch (ctrl)
	{
	case CTRL_SYNC :		/* Make sure that no pending write process */
		res = RES_OK;
		break;
	case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (DWORD) */
		*(DWORD*)buff = (DWORD) USBH_MSC_Param.MSCapacity;
		res = RES_OK;
		break;
	case GET_SECTOR_SIZE :	/* Get R/W sector size (WORD) */
		*(WORD*)buff = 512;
		res = RES_OK;
		break;
	case GET_BLOCK_SIZE :	/* Get erase block size in unit of sector (DWORD) */
		*(DWORD*)buff = 512;
		break;
	default:
		res = RES_PARERR;
	}
	return res;
}
#endif /* _USE_IOCTL != 0 */
